#!/usr/bin/env python3.7

# This example formulates and solves the following simple MIP model:
#  minimize
#        y1 + y2
#  subject to
#        x1 + 10 <= y1
#        x2 + 11 <= y2
#        y1 + 12 <= y2 + Z*M
#        y2 + 13 <= y1 + (1-Z)*M
#        Z : binary  M: semi-integer

import gurobipy as gp
from gurobipy import *


try:
    # 创建一个模型,gurobipy.Model('模型名')
    # O=[0,0,1,0,0,1,0,0,1]
    #
    # P=[   [1,0,0,0,0,0,-1,0,0],
    #       [0,1,0,0,-1,0,0,0,0],
    #       [0,1,0,0,0,0,0,-1,0],
    #       [0,0,0,0,1,0,0,-1,0],
    #       [0,0,1,0,0,-1,0,0,0],
    #       [0,0,1,0,0,0,0,0,-1],
    #       [0,0,0,0,0,1,0,0,-1] ]
    #
    # R=[-1,-1,-1,-1.5,-1,-1,-1.5]
    m = gp.Model("TTE1")
    # GRB.CONTINUOUS， GRB.BINARY， GRB.INTEGER，GRB.SEMICONT，GRB.SEMIINT
    # 设置参数变量x,y,z，Model.addVar() 一次增加一个变量
    x1 = m.addVar(vtype='C' , name="x1")
    y1 = m.addVar(vtype=GRB.CONTINUOUS , name="y1")
    x2 = m.addVar(vtype=GRB.CONTINUOUS , name="x2")
    y2 = m.addVar(vtype=GRB.CONTINUOUS , name="y2")
    Z  = m.addVar(vtype=GRB.BINARY, name='Z')
    M  = m.addVar(lb=0,vtype=GRB.SEMIINT, name='M')

    # 设置目标函数 求y1+y2的最小值,MINIMIZE是求最小值，字母必须全大写
    m.setObjective(y1 + y2 , GRB.MINIMIZE)

    # 添加第一个约数条件c0: x1 + 10  <= y1
    m.addConstr( x1 + 10  <= y1, "c0")

    # 添加第二个约束条件c1: x2 + 11 <= y2
    m.addConstr( x2 + 11 <= y2, "c1")

    # 添加第三个双线性约束条件bilinear0: y1 + 12 <= y2 + Z*M
    m.addConstr( y1 + 12 <= y2 + Z*M, "bilinear0")

    # # 添加第四个双线性约束条件bilinear1: y2 + 13 <= y1 + (1-Z)*M
    m.addConstr( y2 + 13 <= y1 + (1-Z)*M, "bilinear1")

    # m.addGenConstrMin(Z,[x1,y1,M], name="bilenear3") 广义的约束条件
    #m.addConstr(Z == min_(x1,y1 ,M),name="bilinear3") #一般的约束条件


    #m.write('Test1_.lp')
    # 开始求解
    m.optimize()
    '''m.getVars()获取优化结果后的变量的值，返回的变量以集合{}或列表[]显示,然后遍历列表或集合中的变量，将其打印输出'''
    for v in m.getVars():
        print('%s %g' % (v.varName, v.x))

    print('Obj: %g' % m.objVal)  #objVal：（获取单独的优化目标结果值）
    print('-'*50)
    print(m.getVarByName('y1')) #从变量的名称中检索变量。如果多个变量有相同的名称，则此方法选择任意一个。如果没有变量具有该名称，则返回null。

except gp.GurobiError as e:
    print('Error code ' + str(e.errno) + ': ' + str(e))

except AttributeError: #属性错误
    print('Encountered an attribute error')
